package org.zjvis.datascience.web.controller;
import java.io.IOException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.service.MinioService;
import org.zjvis.datascience.service.kg.KnowledgeGraphService;

@RequestMapping("/knowledge-graph")
@RestController
public class KnowledgeGraphController {

    @Autowired
    KnowledgeGraphService knowledgeGraphService;

    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder().build();

    @Value("${restful.knowledgeGraph.url:#{null}}")
    private String KG_SERVICE_API;

    @PostMapping("/preview")
    public ResponseEntity<String> preview(@RequestParam MultipartFile owlFile) {
        try {
            Response response = knowledgeGraphService.queryNebulaWithFile(
                "preview",
                owlFile,
                new ConcurrentHashMap<>()
            );
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @PostMapping("/upload")
    public ResponseEntity<String> upload(
        @RequestParam MultipartFile owlFile,
        @RequestParam String category
    ) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("category", category);
            params.put("userId", String.valueOf(JwtUtil.getCurrentUserId()));
            Response response = knowledgeGraphService.
                queryNebulaWithFile("upload", owlFile, params);
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/previewById")
    @ResponseBody
    public ResponseEntity<String> previewById(@RequestParam Long knowledgeGraphFileId)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebulaByGet(queryParam, "previewById");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/updateFileNameById")
    public ResponseEntity<String> updateFileNameById(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String filename)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        queryParam.put("filename", filename);
        Response response = knowledgeGraphService.queryNebula(queryParam, "updateFileNameById");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/deleteById")
    public ResponseEntity<String> deleteById(@RequestParam Long knowledgeGraphFileId)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "deleteById");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/updateCategoryById")
    public ResponseEntity<String> updateCategoryById(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String category)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        queryParam.put("category", category);
        Response response = knowledgeGraphService.queryNebula(queryParam, "updateCategoryById");
        return ResponseEntity.status(response.code()).body(response.body().string());

}

    @GetMapping("/downloadById")
    @ResponseBody
    public ResponseEntity<InputStreamSource> downloadById(@RequestParam Long knowledgeGraphFileId)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebulaByGet(queryParam, "downloadById");
        return ResponseEntity
            .status(response.code())
            .body(
                new InputStreamResource(response.body().byteStream())
            );
    }

    @PostMapping("/queryByUserId")
    public ResponseEntity<String> queryByUserId() throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("userId", String.valueOf(JwtUtil.getCurrentUserId()));
        Response response = knowledgeGraphService.queryNebula(queryParam, "queryByUserId");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/queryByProjectId")
    public ResponseEntity<String> queryByProjectId(@RequestParam Long projectId)
        throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("projectId", String.valueOf(projectId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "queryByProjectId");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/bindProject")
    public ResponseEntity<String> bindProject(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam Long projectId)
        throws IOException
    {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("projectId", String.valueOf(projectId));
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "bindProject");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/unbindProject")
    public ResponseEntity<String> unbindProject(@RequestParam Long projectId) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("projectId", String.valueOf(projectId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "unbindProject");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/query")
    public ResponseEntity<String> query(
        @RequestParam String hasRelation,
        @RequestParam String withClass,
        @RequestParam Long projectId
    ) throws IOException {
        okhttp3.RequestBody formBody = new MultipartBody.Builder()
            .addFormDataPart("hasRelation", hasRelation)
            .addFormDataPart("withClass", withClass)
            .addFormDataPart("projectId", String.valueOf(projectId))
            .build();
        Request request = new Request.Builder()
            .url(KG_SERVICE_API + "query")
            .post(formBody)
            .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/expand")
    public ResponseEntity<String> expand(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String vertxName
    ) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("vertxName", vertxName);
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "expand");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/collapse")
    public ResponseEntity<String> collapse(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String vertxName,
        @RequestParam String hasEdges
    ) throws IOException {
        okhttp3.RequestBody formBody = new MultipartBody.Builder()
                .addFormDataPart("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId))
                .addFormDataPart("vertxName", vertxName)
                .addFormDataPart("hasEdges", String.valueOf(hasEdges))
                .build();
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "collapse")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/queryPanelInfoByVid")
    public ResponseEntity<String> queryPanelInfoByVid(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String objectName
    ) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("objectName", objectName);
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebulaByGet(queryParam, "queryPanelInfoByVid");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/updatePanelInfoByVid")
    public ResponseEntity<String> updatePanelInfoByVid(
        @RequestParam Long knowledgeGraphFileId,
        @RequestParam String objectName,
        @RequestParam String layout
    ) throws IOException {
        okhttp3.RequestBody formBody = new MultipartBody.Builder()
            .addFormDataPart("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId))
            .addFormDataPart("layout", layout)
            .addFormDataPart("objectName", objectName)
            .build();
        Request request = new Request.Builder()
            .url(KG_SERVICE_API + "updatePanelInfoByVid")
            .post(formBody)
            .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/resetPanelInfoByVid")
    public ResponseEntity<String> resetPanelInfoByVid (
        @RequestParam Long knowledgeGraphFileId, @RequestParam String objectName
    ) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        queryParam.put("objectName", String.valueOf(objectName));
        Response response = knowledgeGraphService.queryNebula(queryParam, "resetPanelInfoByVid");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/queryKGDashBoard")
    public ResponseEntity<String> queryKGDashboard(@RequestParam Long knowledgeGraphFileId)
        throws IOException
    {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebulaByGet(queryParam, "queryKGDashBoard");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/search")
    public ResponseEntity<String> search(@RequestParam Long knowledgeGraphFileId,
        @RequestParam String searchInput
    ) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        queryParam.put("searchInput", String.valueOf(searchInput));
        Response response = knowledgeGraphService.queryNebula(queryParam, "search");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/updateGisInfo")
    public ResponseEntity<String> updateGisInfo(@RequestParam Long knowledgeGraphFileId,
        @RequestParam String layout
    ) throws IOException {
        okhttp3.RequestBody formBody = new MultipartBody.Builder()
            .addFormDataPart("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId))
            .addFormDataPart("layout", layout)
            .build();
        Request request = new Request.Builder()
            .url(KG_SERVICE_API + "updateGisInfo")
            .post(formBody)
            .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }
    
    @PostMapping("/publish")
    public ResponseEntity<String> publish(@RequestParam Long knowledgeGraphFileId
    ) throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        queryParam.put("knowledgeGraphFileId", String.valueOf(knowledgeGraphFileId));
        Response response = knowledgeGraphService.queryNebula(queryParam, "publish");
        return ResponseEntity.status(response.code()).body(response.body().string());
    }
}